package com.basker.pisces.orm.session;

import java.util.List;
import java.util.Map;

import com.basker.pisces.core.RowContract;
import com.basker.pisces.core.exception.StaleObjectException;
import com.basker.pisces.core.meta.IDataObjectMeta;
import com.basker.pisces.core.meta.row.RowContractMeta;
import com.basker.pisces.orm.parser.ISqlParser;

/**
 * 访问SQL的会话实例
 *
 * @author hangwen
 */
public interface ISqlSession extends AutoCloseable {

    /**
     * 删除数据对象
     *
     * @param objectMeta 对象元信息
     * @param id         主键值
     */
    void delete(IDataObjectMeta objectMeta, Object id);

    /**
     * 删除多个数据对象
     *
     * @param objectMeta 对象元信息
     * @param ids        主键数组
     */
    void delete(IDataObjectMeta objectMeta, Object[] ids);

    /**
     * 执行sql语句
     *
     * @param sql
     */
    void execute(String sql);

    /**
     * 填充外键字段的值
     *
     * @param objectMeta  对象元信息
     * @param dataObjects 待 填充的对象
     */
    void fillReferenceFields(IDataObjectMeta objectMeta, Object[] dataObjects);

    /**
     * 获取当前会员访问数据源对应的Sql解析器
     *
     * @return
     */
    ISqlParser getSqlParser();

    /**
     * 通过主键加载一个数据对象
     *
     * @param objectMeta 对象元信息
     * @param id         主鍵值
     * @param useCache   是否从缓存加载
     * @param forUpdate  是否读取最新记录（即忽略脏读）,<b>如在事务内数据库会锁定符合条件的记录
     * @return
     */
    Object load(IDataObjectMeta objectMeta, Object id, boolean useCache, boolean forUpdate);

    /**
     * 通过批量主键加载数据对象
     *
     * @param objectMeta 对象元信息
     * @param ids        主鍵值
     * @param useCache   是否从缓存加载
     * @param forUpdate  是否读取最新记录（即忽略脏读）,<b>如在事务内数据库会锁定符合条件的记录
     * @return
     */
    Object[] loadBatch(IDataObjectMeta objectMeta, Object[] ids, boolean useCache, boolean forUpdate);

    /**
     * 执行查询sql，返回多条Map
     *
     * @param sql  查询语句
     * @param args 参数值
     * @return
     */
    List<Map<String, Object>> queryForList(String sql, Object[] args);

    // PageRowList queryForRows

    /**
     * 执行查询sql，返回多条Map
     *
     * @param sql      查询语句
     * @param args     参数值
     * @param argTypes 参数值的类型
     * @return
     */
    List<Map<String, Object>> queryForList(String sql, Object[] args, int[] argTypes);

    /**
     * 执行查询sql，返回一条Map
     *
     * @param sql  查询语句
     * @param args 参数值
     * @return
     */
    Map<String, Object> queryForMap(String sql, Object[] args);

    /**
     * 执行查询sql，返回一条Map
     *
     * @param sql      查询语句
     * @param args     参数值
     * @param argTypes 参数值的类型
     * @return
     */
    Map<String, Object> queryForMap(String sql, Object[] args, int[] argTypes);

    /**
     * 执行查询sql,返回单行单列
     *
     * @param <TResult>
     * @param requiredType
     * @param sql
     * @param args
     * @return
     */
    <TResult> TResult queryForObject(Class<TResult> requiredType, String sql, Object[] args);

    /**
     * 执行查询sql,返回单行单列
     *
     * @param <TResult>
     * @param requiredType
     * @param sql
     * @param args
     * @param argTypes
     * @return
     */
    <TResult> TResult queryForObject(Class<TResult> requiredType, String sql, Object[] args, int[] argTypes);

    /**
     * 通过where语句，查询指定对象
     *
     * @param objectMeta 对象元信息
     * @param whereSql   查询条件，目前只支持纯数据库sql，参数值用?代替
     * @param args       参数值
     * @param useCache   是否从缓存加载
     * @param forUpdate  是否读取最新记录（即忽略脏读）,<b>如在事务内数据库会锁定符合条件的记录
     * @return
     */
    Object[] queryForObjects(IDataObjectMeta objectMeta, String whereSql, Object[] args, boolean useCache,
                             boolean forUpdate);

    /**
     * 通过where语句，查询指定对象
     *
     * @param objectMeta 对象元信息
     * @param whereSql   查询条件，目前只支持纯数据库sql，参数值用?代替
     * @param args       参数值
     * @param argTypes   参数值的类型
     * @param useCache   是否从缓存加载
     * @param forUpdate  是否读取最新记录（即忽略脏读）,<b>如在事务内数据库会锁定符合条件的记录
     * @return
     */
    Object[] queryForObjects(IDataObjectMeta objectMeta, String whereSql, Object[] args, int[] argTypes,
                             boolean useCache, boolean forUpdate);

    /**
     * 执行分页查询sql，返回多条Map的实例
     *
     * @param sql       查询语句
     * @param pageIndex 页索引 从0开始
     * @param pageSize  每页大小
     * @param args      参数值
     * @return
     */
    List<Map<String, Object>> queryForPageList(String sql, int pageIndex, int pageSize, Object[] args);

    /**
     * 执行分页查询sql，返回多条Map的实例
     *
     * @param sql       查询语句
     * @param pageIndex 页索引 从0开始
     * @param pageSize  每页大小
     * @param args      参数值
     * @param argTypes  参数值的类型
     * @return
     */
    List<Map<String, Object>> queryForPageList(String sql, int pageIndex, int pageSize, Object[] args, int[] argTypes);

    /**
     * 执行分页查询，返回多条行对象
     *
     * @param rowMeta   行的元数据
     * @param sql       查询语句
     * @param pageIndex 页索引 从0开始
     * @param pageSize  每页大小
     * @param args      参数值
     * @return
     */
    List<RowContract> queryForPageRows(RowContractMeta rowMeta, String sql, int pageIndex, int pageSize, Object[] args);

    /**
     * 执行分页查询，返回多条行对象
     *
     * @param rowMeta   行的元数据
     * @param sql       查询语句
     * @param pageIndex 页索引 从0开始
     * @param pageSize  每页大小
     * @param args      参数值
     * @param argTypes  参数值的类型
     * @return
     */
    List<RowContract> queryForPageRows(RowContractMeta rowMeta, String sql, int pageIndex, int pageSize, Object[] args,
                                       int[] argTypes);

    /**
     * 执行查询sql，返回多条行对象
     *
     * @param rowMeta 行的元数据
     * @param sql     查询语句
     * @param args    参数值
     * @return
     */
    List<RowContract> queryForRows(RowContractMeta rowMeta, String sql, Object[] args);

    /**
     * 执行查询sql，返回多条行对象
     *
     * @param rowMeta  行的元数据
     * @param sql      查询语句
     * @param args     参数值
     * @param argTypes 参数值的类型
     * @return
     */
    List<RowContract> queryForRows(RowContractMeta rowMeta, String sql, Object[] args, int[] argTypes);

    /**
     * 保存数据对象，如果保存成功返回对象Id
     *
     * @param objectMeta 对象元信息
     * @param dataObject 待保存的对象
     * @return
     */
    Object save(IDataObjectMeta objectMeta, Object dataObject) throws StaleObjectException;

    /**
     * 保存数据对象，返回保存成功的对象Id
     *
     * @param objectMeta  对象元信息
     * @param dataObjects 待保存的对象
     * @return
     */
    Object[] save(IDataObjectMeta objectMeta, Object[] dataObjects) throws StaleObjectException;

    /**
     * 执行数据操作语句 ，包括insert、update、delete
     *
     * @param sql  操作语句
     * @param args 参数
     * @return
     */
    int update(String sql, Object[] args);

    /**
     * 执行数据操作语句 ，包括insert、update、delete
     *
     * @param sql      操作语句
     * @param args     参数
     * @param argTypes 参数类型
     * @return
     */
    int update(String sql, Object[] args, int[] argTypes);

}
